package com.xh.poster.core.decorators;

import com.xh.poster.core.abst.AbstractPosterDecorator;
import com.xh.poster.core.abst.Poster;
import com.xh.poster.font.DecorationEnum;
import com.xh.poster.font.FontFamilyEnum;
import com.xh.poster.utils.FontUtil;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import sun.font.FontDesignMetrics;

import java.awt.*;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.util.HashMap;
import java.util.Objects;

/**
 * 文本装饰
 *
 * @author yangXS
 * @Date 2020/11/21
 * @since 1.0
 */
@Slf4j
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
public class TextDecorator extends AbstractPosterDecorator {

    /**
     * 字体
     */
    private Font font = new Font(null);

    /**
     * 文字装饰
     */
    private DecorationEnum decorationEnum = DecorationEnum.NONE;

    /**
     * 字体
     */
    private FontFamilyEnum fontFamilyEnum = FontFamilyEnum.PING_FANG_SC_MEDIUM;

    /**
     * 字体样式
     */
    private int fontStyle = Font.PLAIN;

    /**
     * 字体大小
     */
    private int fontSize = 16;

    /**
     * 字体颜色
     */
    private Color color = new Color(0, 0, 0);

    /**
     * 内容
     */
    private String content;

    /**
     * 是否包含删除线
     */
    private boolean delLine = false;

    /**
     * 是否居中
     */
    private boolean center;

    /**
     * 是否根据 width 换行, 配合 width 使用
     */
    private boolean canNewLine = false;

    /**
     * 换行限制次数
     */
    private int newLineLimit = 1;

    /**
     * 相对定位对象宽
     */
    private String relativeItemContent;

    /**
     * 相对定位对象字体大小
     */
    private int relativeItemFontSize;

    /**
     * 相对定位对象横坐标值
     */
    private int relativeItemX;

    public TextDecorator(Poster poster) {
        super(poster);
    }

    @Builder(toBuilder = true)
    public TextDecorator(Poster poster, int positionX, int positionY,
                         int width, int height, Font font, int fontSize,
                         Color color, String content, int fontStyle,
                         boolean delLine, boolean canNewLine, int newLineLimit,
                         boolean center, DecorationEnum decorationEnum, FontFamilyEnum fontFamilyEnum,
                         String relativeItemContent, int relativeItemX, int relativeItemFontSize) {
        super(poster, positionX, positionY, width, height);
        this.font = font;
        this.fontSize = fontSize;
        this.color = color;
        this.content = content;
        this.fontStyle = fontStyle;
        this.delLine = delLine;
        this.canNewLine = canNewLine;
        this.newLineLimit = newLineLimit;
        this.center = center;
        this.decorationEnum = decorationEnum;
        this.fontFamilyEnum = fontFamilyEnum;
        this.relativeItemContent = relativeItemContent;
        this.relativeItemX = relativeItemX;
        this.relativeItemFontSize = relativeItemFontSize;
    }

    @Override
    public BufferedImage draw(BufferedImage image) {
        // 绘制 被装饰之前的 图片
        BufferedImage draw = poster.draw(image);
        // 装饰, 绘制文本
        return drawText(draw);
    }

    /**
     * 设置相对定位字体
     *
     * @param image
     */
    public Graphics2D setRelativeFont(BufferedImage image) {
        HashMap<TextAttribute, Object> map = new HashMap<>();

        map.put(TextAttribute.SIZE, relativeItemFontSize);
        // 默认字体family为 苹方-简
        // map.put(TextAttribute.FAMILY, FontFamilyEnum.PING_FANG_SC_MEDIUM.getDesc());
        if (!Objects.equals(fontFamilyEnum.getCode(), FontFamilyEnum.PING_FANG_SC_MEDIUM.getCode())) {
            // 待支持其他字段类型
        }
        if (!Objects.equals(decorationEnum.getCode(), DecorationEnum.NONE.getCode())) {
            // 中划线
            if (Objects.equals(decorationEnum.getCode(), DecorationEnum.LINE_THROUGH.getCode())) {
                map.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
            }
            // 下划线
            if (Objects.equals(decorationEnum.getCode(), DecorationEnum.UNDERLINE.getCode())) {
                map.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
            }
        }

        Font font = FontUtil.getFont();
        font = font.deriveFont(map);
        Graphics2D g = image.createGraphics();
        // 设置文字抗锯齿算法
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setFont(font);
        g.setColor(color);
        return g;
    }

    /**
     * 绘制文本具体实现
     *
     * @param image image
     * @return image
     */
    private BufferedImage drawText(BufferedImage image) {

        if (content == null || content.length() == 0) {
            return image;
        }
        HashMap<TextAttribute, Object> map = new HashMap<>();

        map.put(TextAttribute.SIZE, fontSize);
        map.put(TextAttribute.FAMILY, "微软雅黑");
        // 默认字体family为 苹方-简
//         map.put(TextAttribute.FAMILY, FontFamilyEnum.PING_FANG_SC_MEDIUM.getDesc());
        if (!Objects.equals(fontFamilyEnum.getCode(), FontFamilyEnum.PING_FANG_SC_MEDIUM.getCode())) {
            // 待支持其他字段类型
        }
        if (!Objects.equals(decorationEnum.getCode(), DecorationEnum.NONE.getCode())) {
            // 中划线
            if (Objects.equals(decorationEnum.getCode(), DecorationEnum.LINE_THROUGH.getCode())) {
                map.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
            }
            // 下划线
            if (Objects.equals(decorationEnum.getCode(), DecorationEnum.UNDERLINE.getCode())) {
                map.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
            }
        }
        // 实现绘制文本
        // font = font.deriveFont(fontStyle, fontSize);
        // font = new Font(map);

        Font font = FontUtil.getFont();
        font = font.deriveFont(map);

        Graphics2D g = image.createGraphics();
        // 设置文字抗锯齿算法
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setFont(font);
        g.setColor(color);

        // 文字水平居中实现
        if (center) {
            WritableRaster raster = image.getRaster();
            int width = raster.getWidth();
            int fontWidth = g.getFontMetrics().stringWidth(content);
            positionX = (width - fontWidth) / 2;
        }
        // 相对定位实现
        if (Objects.nonNull(relativeItemContent) && relativeItemContent.length() > 0 && relativeItemFontSize > 1) {
            Graphics2D graphics2D = setRelativeFont(image);
            int fontWidth = graphics2D.getFontMetrics().stringWidth(relativeItemContent);
            positionX = fontWidth + relativeItemX;
        }

        FontMetrics fm = FontDesignMetrics.getMetrics(font);
        // 换行 并且 设置的换行宽度大于一个字的大小才可以换行
        if (canNewLine && width > fontSize) {
            //【商品名称换行判断逻辑】
            // 换行修正最后一个文字越界.
            width = width - fontSize / 2;

            int charWidth = 0;
            int lineLimit = newLineLimit;
            StringBuilder sb = new StringBuilder();

            for (int i = 0; lineLimit >= 0 && i < content.length(); i++) {
                charWidth += fm.charWidth(content.charAt(i));
                sb.append(content.charAt(i));
                // 如果宽度 > width 换行
                if (charWidth > width * (newLineLimit - lineLimit + 1)) {
                    g.drawString(sb.toString(), positionX, positionY + fontSize + (newLineLimit - lineLimit) * fontSize);
                    sb.setLength(0);
                    lineLimit--;
                    continue;
                }
                // 如果超过 换行次数限制 则后面省略 改为...
                if (charWidth > width * (newLineLimit + 1) - 2 * fontSize) {
                    sb.append("...");
                    g.drawString(sb.toString(), positionX, positionY + fontSize + (newLineLimit - lineLimit) * fontSize);
                    break;
                }
                // 如果前两个if没有进，则直接添加
                if (i == content.length() - 1) {
                    g.drawString(sb.toString(), positionX, positionY + fontSize + ((newLineLimit - lineLimit)) * fontSize);
                }
            }

        } else {
            g.drawString(content, positionX, positionY + fontSize);
        }

        // 删除线暂时不支持换行
        if (delLine && !canNewLine) {
            // 删除线长度
            int delLineW = fm.stringWidth(content);
            g.drawLine(positionX, positionY + 3 * fontSize / 5, positionX + delLineW, positionY + 3 * fontSize / 5);
        }

        g.dispose();
        return image;
    }

}
